#include "protocol.hpp"
#include "socket.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <unistd.h>

class TcpClient
{
public:
    TcpClient(const std::string &ip, uint16_t port) : _ip(ip), _port(port)
    {
        _sock = new NetWork::TcpSocket();
    }
    ~TcpClient()
    {
        _sock->CloseSockFd();
        delete _sock;
    }
    void Init()
    {
        if (!_sock->BuildConnectSocketMethod(_ip, _port))
        {
            std::cerr << "connect server failed, error code: " << errno << ", error message: " << strerror(errno) << std::endl;
        }
        std::cout << "client fd = " << _sock->GetSockFd() << std::endl;
        std::cout << "connect server success" << std::endl;
    }
    void AskCal()
    {
        // 客户端已经完成链接, 开始执行客户端代码
        std::unique_ptr<Protocol::Factory> factory = std::make_unique<Protocol::Factory>();

        // request->Print();

        srand(time(nullptr) ^ getpid());
        const std::string opers = "+-*/%^=&";
        while (1)
        {
            // 1. 构建一个请求，并发送
            int x = rand() % 100; //[0, 99]
            usleep(rand() % 7777);
            int y = rand() % 100; //[0,99]
            char oper = opers[rand() % opers.size()];
            // 创建结构化数据
            std::shared_ptr<Protocol::Request> request = factory->BuildRequest(x, y, oper);

            // request->Print(); // debug
            // 将request序列化
            std::string send_request;
            request->Serialize(&send_request);

            // 添加报头形成报文
            send_request = Protocol::Encode(send_request);

            // 发送请求
            _sock->Send(send_request);

            while (1)
            {
                // 2.读取回应
                std::string recv_response;
                if (_sock->Recv(&recv_response, 1024) == false)
                {
                    std::cout << "Recv debug" << std::endl;
                    break;
                }

                // 解析除去报头
                std::string resp;
                if (Protocol::Decode(recv_response, &resp) == false)
                    continue;
                // 反序列化
                std::shared_ptr<Protocol::Response> response = factory->BuildResponse();
                response->Deserialize(resp);
                // 获取了结构化数据response
                std::cout << x << " " << oper << " " << y << " = " << response->GetResult() << ", code: " << response->GetCode() << std::endl;
                break;
            }
            sleep(1);
        }
    }

private:
    NetWork::Socket *_sock;
    uint16_t _port;
    std::string _ip;
};